
package jrain.fw.http.common.rest.impl;

import java.io.IOException;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jrain.fw.core.business.BusinessConst;
import jrain.fw.core.business.BusinessRequest;
import jrain.fw.core.business.BusinessResponse;
import jrain.fw.core.log.Logger;
import jrain.fw.core.log.LoggerFactory;
import jrain.fw.core.rest.RestMethod;
import jrain.fw.core.rest.RestService;
import jrain.fw.core.utils.FwUtils;
import jrain.fw.http.common.consts.ContentType;
import jrain.utils.collection.CollectionUtils;
import jrain.utils.lang.StringUtils;

/**
 * <pre>
 * 作者：3244924214@qq.com 
 * 描述：RestAciton
 * </pre>
 */
@RestService()
public class RestAction {

	private static final Logger log = LoggerFactory.getLogger("http-rest-action");

	@RestMethod(name = "/rest*")
	public void rest(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException {
		String url = httpRequest.getRequestURI();
		List<String> list = CollectionUtils.valueOfList(url, "/");
		if (list.size() == 3 || list.size() == 4) {
			String service = list.get(1);
			String method = list.get(2);
			String version = list.size() == 3 ? "v1" : list.get(3);
			BusinessRequest request = new BusinessRequest(service, method, version);
			try {
				// Cookie 处理
				String tempToken = "";
				Cookie[] cookies = httpRequest.getCookies();
				if (cookies != null) {
					for (Cookie cookie : cookies) {
						if (BusinessConst.DATA_TOKEN.equals(cookie.getName())) {
							tempToken = cookie.getValue();
						}
					}
				}
				String headerToken = httpRequest.getHeader(BusinessConst.DATA_TOKEN);
				if (!StringUtils.isEmpty(headerToken)) {
					tempToken = headerToken;
				}
				String contentType = httpRequest.getHeader(BusinessConst.DATA_CONTENT_TYPE);
				// 参数解析
				String params = StringUtils.trimNull(httpRequest.getParameter(BusinessConst.REQ_PARAMS));
				String paramType = StringUtils.trimNull(httpRequest.getParameter(BusinessConst.REQ_PARAM_TYPE));
				log.trace("params:{}{}{}",request.getKey(),paramType,params);
				
				// 普通参数
				if (StringUtils.isEmpty(paramType)) {
					// 默认参数类型
					if (!StringUtils.isEmpty(params)) {
						Map<String, Object> dataMap = FwUtils.getJsonService().toMap(params);
						request.setData(dataMap);
					}
				} else if (paramType.startsWith(BusinessConst.REQ_PARAM_PRE)) {
					// 前缀参数类型
					String preData = paramType.substring(4);
					int preDataLength = preData.length() + 1;
					Enumeration<?> names = httpRequest.getParameterNames();
					while (names.hasMoreElements()) {
						String name = StringUtils.trimNull(names.nextElement());
						if (name.startsWith(preData + "_") && name.length() >= preDataLength) {
							String key = name.substring(preDataLength);
							Object value = httpRequest.getParameter(name);
							request.putData(key, value);
							log.trace("params:{}{}{}",request.getKey(),key,value);
						}
					}
				}
				// 扩展参数
				final String token = tempToken;
				Consumer<BusinessRequest> consumer = new Consumer<BusinessRequest>() {
					@Override
					public void accept(BusinessRequest t) {
						t.putExtData(BusinessConst.EXT_TOKEN_ID, token);
						t.putExtData(BusinessConst.EXT_REQUEST, httpRequest);
						t.putExtData(BusinessConst.EXT_RESPONSE, httpResponse);
						t.putExtData(BusinessConst.EXT_CONTENT_TYPE, contentType);
					}
				};
				// 响应数据格式
				BusinessResponse response = FwUtils.getBusinessApiClient().doSync(request, consumer);
				String rsContentType = StringUtils.trimNull(response.getExtData(BusinessConst.RS_CONTENT_TYPE));
				if (StringUtils.isEmpty(rsContentType)) {
					httpResponse.setContentType(ContentType.APPLICATION_JSON_UTF8);
				} else {
					httpResponse.setContentType(rsContentType);
				}
				// 响应数据是否JSON
				String rsContentSteam = StringUtils.trimNull(response.getExtData(BusinessConst.RS_CONTENT_STEAM));
				if (StringUtils.isEmpty(rsContentSteam)) {
					String data = FwUtils.getJsonService().toPageJson(response);
					write(httpResponse, data);
				}
			} catch (Throwable t) {
				log.warn("error url=" + url, t);
				write(httpResponse, "{\"code\":500,\"msg\":\"" + t.getMessage() + "\"}");
			}
		} else {
			log.warn("error url={}", url);
			write(httpResponse, "{\"code\":404}");
		}
	}

	private void write(HttpServletResponse response, String data) {
		try {
			if (!StringUtils.isEmpty(data)) {
				response.getWriter().write(data);
			}
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
	}

}
